/**
 * @description Datepicker 期间日期选择器
 * @author pengyajun
 */

/**
 * eg: 
 * 
 *    this.state = {
            openDatePicker: false,
            currDateKey: '',
            date1: {
                startDate: '',
                endDate: null
            },
            date2: {
                startDate: '',
                endDate: null
            },
            date3: {
                startDate: '2018-12-09',
                endDate: null
            }
        };
 * 
 *     <TouchableOpacity activeOpacity={1} onPress={() => this.setState({ openDatePicker: true, currDateKey: 'date1' })}>
            <Text style={{ height: 40 }}>选择时间：{this.state.date1.startDate}--{this.state.date1.endDate}</Text>
        </TouchableOpacity>
        <TouchableOpacity activeOpacity={1} onPress={() => this.setState({ openDatePicker: true, currDateKey: 'date2' })}>
            <Text style={{ height: 40 }}>选择时间：{this.state.date2.startDate}--{this.state.date2.endDate}</Text>
        </TouchableOpacity>
        <TouchableOpacity activeOpacity={1} onPress={() => this.setState({ openDatePicker: true, currDateKey: 'date3' })}>
            <Text style={{ height: 40 }}>选择时间：{this.state.date3.startDate}--{this.state.date3.endDate}</Text>
        </TouchableOpacity>

        <DateGapPicker
            isVisible={this.state.openDatePicker}
            date={this.state[this.state.currDateKey]}
            cb={(newDate) => {
                this.setState({ openDatePicker: false })
                if (!newDate) return;
                this.setState({
                    [this.state.currDateKey]: {
                        startDate: newDate.startDate,
                        endDate: newDate.endDate
                    }
                })

            }}></DateGapPicker>
 * 
 * 
 */

import React, { Component } from 'react';
import { Animated, StyleSheet, ScrollView, Modal, View, Text, PixelRatio, TouchableOpacity } from "react-native";
import { GLOBAL } from '../../config/global';
import moment from 'moment';
import COLORS from '../../theme/colors';

const scale = GLOBAL.SCALE;
const WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];

export default class DateGapPicker extends Component {

  DATE_COLLECTION = [];

  constructor(props) {
    super(props);
    this.state = {
      bottom: new Animated.Value(-500),
      isVisible: this.props.isVisible,
      startDate: {},
      endDate: {},
      limitStart: '', //eg: 2018-12-01
      limitEnd: '' //eg: 2019-12-01
    }
  }

  componentWillMount () {
    this.prepare();
  }

  componentWillReceiveProps (props) {
    if (!props || !props.date) return;
    this.setState({
      isVisible: props.isVisible,
      startDate: props.date.startDate || '',
      endDate: props.date.endDate || '',
      limitStart: props.date.limitStart || '',
      limitEnd: props.date.limitEnd || ''
    })
  }

  prepare () {
    const MONTHS = 24; //准备12个月的数据
    let now = moment();
    for (let i = 0; i < MONTHS; i++) {
      let month = now.add(i == 0 ? 0 : 1, 'months');
      let daysCnt = this.getCountDaysByAddMonths(i);
      let days = [];
      let firstDay = moment(month.format('YYYY-MM-') + '01');
      for (let j = 0; j < daysCnt; j++) {
        let date = firstDay.add(j == 0 ? 0 : 1, 'days');
        let day = {
          date: date.format('YYYY-MM-DD'),
          day: date.format('D'),
          weekdayIndex: date.weekday(),
          weekdayStr: WEEKDAYS[date.weekday()],
          title: date.format('YYYY年MM月DD日')
        };
        days.push(day)
      }
      this.addPlaceholder(days);
      this.DATE_COLLECTION.push({
        title: month.format('YYYY年MM月'),
        days: days
      })
    }
  }

  addPlaceholder (days) {
    let frontCnt = days[0].weekdayIndex;
    let endCnt = 6 - days[days.length - 1].weekdayIndex;
    for (let i = 0; i < frontCnt; i++) {
      days.splice(0, 0, { date: null })
    }
    for (let i = 0; i < endCnt; i++) {
      days.push({ date: null })
    }
  }

  getCountDaysByAddMonths (increment) {
    let curDate = new Date();
    return new Date(curDate.getFullYear(), curDate.getMonth() + increment + 1, 0).getDate();
  }

  show () {
    Animated.timing(this.state.bottom, {
      toValue: 0,
      duration: 150,
    }).start();
  }

  hide () {
    let { cb } = this.props;
    Animated.timing(this.state.bottom, {
      toValue: -500 * scale,
      duration: 150,
    }).start();
    cb(null, true)
  }

  callback (data) {
    let { cb, double } = this.props;
    this.hide();
    setTimeout(() => {
      this.setState({
        isVisible: false
      }, () => {
        if (double && data && !data.endDate) data.endDate = data.startDate;
        cb(data)
      })
    }, 150)
  }

  render () {
    return (
      <Modal
        animationType="none"
        transparent={true}
        style={styles.modalContainer}
        visible={this.state.isVisible}
        onShow={() => this.show()}
        onRequestClose={() => { console.log('react-native Modal') }}
      >
        <TouchableOpacity activeOpacity={1} style={styles.modalBackdrop} onPress={() => this.callback()}>
        </TouchableOpacity>
        <Animated.View style={[styles.contentContainer, { bottom: this.state.bottom }]}>
          <DateGapPickerContent
            DATE_COLLECTION={this.DATE_COLLECTION}
            startDate={this.state.startDate}
            endDate={this.state.endDate}
            limitStart={this.state.limitStart}
            limitEnd={this.state.limitEnd}
            cb={(data) => this.callback(data)}
          ></DateGapPickerContent>
        </Animated.View>
      </Modal >
    )
  }
}

class DateGapPickerContent extends Component {

  dateCollIndex = 0;
  dateCollOffset = 2;

  constructor(props) {
    super(props);

    this.state = {
      dateColl: [],
      startDate: this.getDateObjByStr(this.props.startDate),
      endDate: this.getDateObjByStr(this.props.endDate),
      limitStart: this.props.limitStart || moment().format('YYYY-MM-DD'),
      limitEnd: this.props.limitEnd || ''
    }
  }

  componentWillMount () {
    this.loadDateColl();
  }

  loadDateColl () {
    let { DATE_COLLECTION } = this.props;
    if (this.dateCollIndex > DATE_COLLECTION.length) return;
    let _dateColl = [...this.state.dateColl];
    for (let i = 0; i < this.dateCollOffset; i++) {
      if (this.dateCollIndex + i > DATE_COLLECTION.length) return;
      _dateColl = [..._dateColl, { ...DATE_COLLECTION[this.dateCollIndex + i] }]
    }
    this.setState({
      dateColl: this._updateDateColl(null, null, _dateColl)
    }, () => {
      this.dateCollIndex = this.dateCollIndex + this.dateCollOffset;
    })
  }

  isBetween (date, start, end) {
    return moment(date).isSame(start) || moment(date).isSame(end) || (start && end && moment(date).isBetween(start, end));
  }

  isDisable (date) {
    return !!(this.state.limitStart && moment(date).isBefore(this.state.limitStart)) || !!(this.state.limitEnd && moment(date).isAfter(this.state.limitEnd));
  }

  isSame (source, target) {
    return source && target && moment(source).isSame(target);
  }

  getDateObjByStr (str) {
    if (!str) return {};
    let date = moment(str);
    return {
      date: date.format('YYYY-MM-DD'),
      day: date.format('D'),
      weekdayIndex: date.weekday(),
      weekdayStr: WEEKDAYS[date.weekday()],
      title: date.format('YYYY年MM月DD日')
    }
  }

  _updateDateColl (start, end, dateColl) {
    start = start || this.state.startDate;
    end = end || this.state.endDate;
    let _dateColl = [...(dateColl || this.state.dateColl)];
    for (let month of _dateColl) {
      for (let day of month.days) {
        if (day.date) {
          day.isDisable = this.isDisable(day.date);
          day.isBetween = this.isBetween(day.date, start.date, end.date);
          day.isStart = this.isSame(day.date, start.date);
          day.isEnd = this.isSame(day.date, end.date);
        }
      }
    }
    return _dateColl;
  }

  select (day) {
    if (this.isDisable(day.date)) return;
    let _dateColl, start, end;
    if (!this.state.startDate.date || (this.state.startDate.date && this.state.endDate.date) || moment(day.date).isBefore(this.state.startDate.date)) {
      start = day;
      end = {};
      _dateColl = this._updateDateColl(start, end, null);
    } else {
      start = this.state.startDate;
      end = day;
      _dateColl = this._updateDateColl(start, end, null);
    }
    this.setState({
      startDate: start,
      endDate: end,
      dateColl: _dateColl
    })
  }

  clear () {
    this.setState({
      startDate: '',
      endDate: '',
      dateColl: this._updateDateColl({}, {}, null)
    })
  }

  // 监听底部 增加时间
  scroll = (e) => {
    var offsetY = e.nativeEvent.contentOffset.y; //滑动距离
    var contentSizeHeight = e.nativeEvent.contentSize.height; //scrollView contentSize高度
    var oriageScrollHeight = e.nativeEvent.layoutMeasurement.height; //scrollView高度
    if (offsetY + oriageScrollHeight + 30 >= contentSizeHeight) {
      this.loadDateColl();
    }
  }

  render () {
    let { cb } = this.props;
    return (
      <View style={styles.modalContent}>
        <View style={styles.btnsContainer}>
          <TouchableOpacity style={styles.btn} onPress={() => this.clear()}><Text>清除</Text></TouchableOpacity>
          <TouchableOpacity style={styles.btn} onPress={() => {
            cb({
              startDate: this.state.startDate.date || '',
              endDate: this.state.endDate.date || ''
            }, true)
          }}><Text style={{ color: COLORS.primaryColor }}>确定</Text></TouchableOpacity>
        </View>
        <View style={styles.selectedContainer}>
          <View style={styles.selectedItem}>
            {
              this.state.startDate && this.state.startDate.date ? (
                <View>
                  <Text style={styles.selectedText}>{this.state.startDate.weekdayStr}</Text>
                  <Text style={styles.selectedText}>{this.state.startDate.title}</Text>
                </View>
              ) : (<View><Text style={styles.selectedTextDefault}>开始</Text></View>)
            }
          </View>
          <View style={styles.selectedItem}>
            {
              this.state.endDate && this.state.endDate.date ? (
                <View>
                  <Text style={styles.selectedText}>{this.state.endDate.weekdayStr}</Text>
                  <Text style={styles.selectedText}>{this.state.endDate.title}</Text>
                </View>
              ) : (<View><Text style={styles.selectedTextDefault}>结束</Text></View>)
            }
          </View>
        </View>
        <View style={styles.weekdayContainer}>
          <Text style={styles.weekdayItem}>日</Text>
          <Text style={styles.weekdayItem}>一</Text>
          <Text style={styles.weekdayItem}>二</Text>
          <Text style={styles.weekdayItem}>三</Text>
          <Text style={styles.weekdayItem}>四</Text>
          <Text style={styles.weekdayItem}>五</Text>
          <Text style={styles.weekdayItem}>六</Text>
        </View>
        <ScrollView
          onScroll={this.scroll}
          showsVerticalScrollIndicator={false}
        >
          {
            this.state.dateColl.map((month, mIndex) => {
              return (
                <View key={mIndex}>
                  <Text style={styles.monthTitle}>{month.title}</Text>
                  <View style={styles.daysContainer}>
                    {
                      month.days.map((day, dIndex) => {
                        return (
                          day.date ?
                            <View key={dIndex} style={[styles.dayItem, day.isBetween ? styles.dayItemActive : null, day.isStart ? styles.dayStart : null, day.isEnd ? styles.dayEnd : null]}>
                              <Text
                                style={[styles.dayItemText, day.isDisable ? styles.dayDisable : null, day.isBetween ? styles.dayItemTextActive : null]}
                                onPress={() => { this.select(day) }}
                              >{day.day}</Text>
                              {!(day.isStart && day.isEnd) && day.isStart ? <Text style={styles.dayTips}>开始</Text> : null}
                              {!(day.isStart && day.isEnd) && day.isEnd ? <Text style={styles.dayTips}>结束</Text> : null}
                            </View>
                            : <View key={dIndex} style={styles.dayItem}><Text style={styles.dayItemText}></Text></View>
                        )
                      })
                    }
                  </View>
                </View>
              )
            })
          }
        </ScrollView>
      </View>
    )
  }
}


const styles = StyleSheet.create({
  modalContainer: {
    margin: 0,
  },
  modalBackdrop: {
    backgroundColor: 'rgba(0, 0, 0, 0.65)',
    flex: 1,
  },
  contentContainer: {
    position: 'absolute',
    left: 0,
    right: 0,
    height: 500 * scale,
    backgroundColor: '#FFF',
    borderRadius: 4,
    borderColor: 'rgba(0, 0, 0, 0.1)',
  },
  modalContent: {
    padding: 0,
    paddingBottom: 10 * scale,
    justifyContent: 'center',
    alignItems: 'center',
    height: 500 * scale
  },
  btnsContainer: {
    width: '100%',
    borderBottomWidth: 1 / PixelRatio.get(),
    borderStyle: 'solid',
    borderBottomColor: COLORS.borderColor,
    flexDirection: 'row',
    justifyContent: 'space-around',
  },
  btn: {
    alignItems: 'center',
    padding: 15 * scale,
    width: 180 * scale
  },
  selectedContainer: {
    width: 375 * scale,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingLeft: 20 * scale,
    paddingRight: 20 * scale,
    paddingTop: 16 * scale,
    paddingBottom: 12 * scale
  },
  selectedItem: {
    height: 48 * scale,
  },
  selectedTextDefault: {
    fontSize: 24 * scale,
    height: 48 * scale,
    lineHeight: 48 * scale
  },
  selectedText: {
    fontSize: 20 * scale,
  },
  weekdayContainer: {
    width: 375 * scale,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 8 * scale,
    height: 18 * scale,
    paddingLeft: 12 * scale,
    paddingRight: 12 * scale
  },
  weekdayItem: {
    height: 18 * scale,
    lineHeight: 18 * scale,
    fontSize: 13 * scale,
    textAlign: 'center',
    width: 350 * scale / 7,
    color: COLORS.lightBlack
  },
  monthTitle: {
    width: 375 * scale,
    textAlign: 'left',
    paddingLeft: 20 * scale,
    marginBottom: 3 * scale,
    marginTop: 5 * scale,
    fontSize: 18 * scale,
    color: COLORS.lightBlack
  },
  daysContainer: {
    width: 375 * scale,
    flex: 1,
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'center'
  },
  dayItem: {
    width: 350 * scale / 7,
    height: 35 * scale,
    marginTop: 3 * scale,
    marginBottom: 3 * scale
  },
  dayItemText: {
    width: 350 * scale / 7,
    height: 35 * scale,
    lineHeight: 35 * scale,
    fontSize: 16 * scale,
    color: COLORS.lightBlack,
    textAlign: 'center',
  },
  dayItemActive: {
    backgroundColor: COLORS.primaryColor,
  },
  dayItemTextActive: {
    color: '#FFF'
  },
  dayDisable: {
    color: COLORS.light
  },
  dayStart: {
    borderTopLeftRadius: 10,
    borderBottomLeftRadius: 10
  },
  dayEnd: {
    borderTopRightRadius: 10,
    borderBottomRightRadius: 10
  },
  dayTips: {
    position: 'absolute',
    left: 0,
    bottom: 1 * scale,
    right: 0,
    textAlign: 'center',
    fontSize: 8 * scale,
    color: '#FFF'
  }
})